home *** CD-ROM | disk | FTP | other *** search
- /*
- * CyberX10.c
- *
- * Copyright © 1992 by Christopher A. Wichura (caw@miroc.chi.il.us)
- * All Rights Reserved.
- */
-
- /* stuff for our ReadArgs() call */
-
- #define ARG_TEMPLATE "TARGETS/M,ON/S,OFF/S,DIM/K/N,BASEHC/K,SETCLOCK/S,DIAG/S,DOWNLOAD/K,UPLOAD/K,DEVICE/K,UNIT/K/N,ATTEMPT/S"
- enum ReadArgsArray {
- ARG_TARGETS,
- ARG_ON,
- ARG_OFF,
- ARG_DIM,
- ARG_BASEHC,
- ARG_SETCLOCK,
- ARG_DIAG,
- ARG_DOWNLOAD,
- ARG_UPLOAD,
- ARG_DEVICE,
- ARG_UNIT,
- ARG_ATTEMPT,
- ARG_sizeof
- };
-
- const UBYTE HouseCode[16] =
- {0x60, 0xE0, 0x20, 0xA0, 0x10, 0x90, 0x50, 0xD0, 0x70, 0xF0, 0x30, 0xB0, 0x00, 0x80, 0x40, 0xC0};
-
- struct Library *IconBase;
- struct Library *UtilityBase;
-
- struct LocaleInfo LocaleInfo;
- struct Locale *DefaultLocale;
-
- int __regargs main(char *cmdptr, int cmdlen, struct WBStartup * WBMsg)
- {
- STRPTR WBArgs;
- STRPTR ArgHelp;
- LONG index;
- extern UBYTE __far arg_help[];
- extern UBYTE __far copyright[];
-
- /*
- * the first thing we do is try and open up the locale library and
- * grab our catalog as we will need it if we want to print any error
- * messages or other text
- */
-
- if (LocaleInfo.li_LocaleBase = (APTR) OpenLibrary("locale.library", 38)) {
- DefaultLocale = OpenLocale(NULL); /* autodocs say this is
- * guarenteed a valid
- * return */
- LocaleInfo.li_Catalog = OpenCatalogA(NULL, "CyberX10.catalog", NULL);
- }
-
- /* try and open up utility.library */
- if (UtilityBase = OpenLibrary("utility.library", 37)) {
- if (ArgHelp = AllocVec(strlen(GetString(&LocaleInfo, MSG_ARG_HELP)) + strlen(GetString(&LocaleInfo, MSG_COPYRIGHT)) + strlen(PROGNAME) + strlen(VersionID) + 1, MEMF_CLEAR)) {
- sprintf(ArgHelp, GetString(&LocaleInfo, MSG_ARG_HELP), PROGNAME, VersionID, GetString(&LocaleInfo, MSG_COPYRIGHT));
-
- if (WBMsg) {
- ErrorsToEzReq = TRUE;
-
- if (IconBase = OpenLibrary("icon.library", 37)) {
- for (index = (WBMsg->sm_NumArgs != 1 ? 1 : 0); index < WBMsg->sm_NumArgs; index++) {
- if (WBArgs = WBtoCLIargs(&WBMsg->sm_ArgList[index], ARG_TEMPLATE)) {
- DoInstance(WBArgs, NULL);
- FreeVec(WBArgs);
- }
- }
-
- CloseLibrary(IconBase);
- }
- }
- else
- DoInstance(NULL, ArgHelp);
-
- FreeVec(ArgHelp);
- }
-
- CloseLibrary(UtilityBase);
- }
- else
- ErrorMsg(MSG_COULDNT_OPEN, "utility.library");
-
- if (LocaleInfo.li_LocaleBase) {
- CloseCatalog(LocaleInfo.li_Catalog);
- CloseLocale(DefaultLocale);
- CloseLibrary((struct Library *) LocaleInfo.li_LocaleBase);
- }
- }
-
- /* actually proccess the argument line and do what was requested */
-
- void DoInstance(STRPTR ArgLine, STRPTR ArgHelp)
- {
- struct RDArgs *RArgs, *MyRArgs;
- STRPTR ArgArray[ARG_sizeof];
-
- STRPTR SerDevice;
- ULONG SerUnit;
-
- /* do the stuff needed to call ReadArgs to parse the command line */
- memset(ArgArray, 0, sizeof(ArgArray));
-
- if (MyRArgs = AllocDosObject(DOS_RDARGS, TAG_DONE)) {
- if (ArgLine) {
- MyRArgs->RDA_Source.CS_Buffer = ArgLine;
- MyRArgs->RDA_Source.CS_Length = strlen(ArgLine);
- MyRArgs->RDA_Source.CS_CurChr = 0L;
- }
-
- if (ArgHelp)
- MyRArgs->RDA_ExtHelp = ArgHelp;
- else
- MyRArgs->RDA_Flags |= RDAF_NOPROMPT;
-
- if (RArgs = ReadArgs(ARG_TEMPLATE, (LONG *) & ArgArray, MyRArgs)) {
- if (ArgArray[ARG_DEVICE])
- SerDevice = ArgArray[ARG_DEVICE];
- else
- SerDevice = "serial.device";
-
- if (ArgArray[ARG_UNIT])
- SerUnit = *((LONG *) ArgArray[ARG_UNIT]);
- else
- SerUnit = 0;
-
- if (OpenTimer()) {
- if (OpenSerial(SerDevice, SerUnit, (BOOL) ArgArray[ARG_ATTEMPT])) {
- if (ArgArray[ARG_ON])
- X10TurnOn((STRPTR *) ArgArray[ARG_TARGETS]);
- else if (ArgArray[ARG_OFF])
- X10TurnOff((STRPTR *) ArgArray[ARG_TARGETS]);
- else if (ArgArray[ARG_DIM])
- X10Dim((STRPTR *) ArgArray[ARG_TARGETS], *((LONG *) ArgArray[ARG_DIM]));
- else if (ArgArray[ARG_BASEHC])
- X10SetBaseHC(ArgArray[ARG_BASEHC]);
- else if (ArgArray[ARG_SETCLOCK])
- X10SetClock();
- else if (ArgArray[ARG_DIAG])
- X10Diagnostic();
- else if (ArgArray[ARG_DOWNLOAD])
- X10Download(ArgArray[ARG_DOWNLOAD]);
- else if (ArgArray[ARG_UPLOAD])
- X10Upload(ArgArray[ARG_UPLOAD]);
- else
- ErrorMsg(MSG_NOTHING_TO_DO);
-
- CloseSerial();
- }
- else
- ErrorMsg(MSG_NO_SER_DEV, SerDevice, SerUnit);
-
- CloseTimer();
- }
- else
- ErrorMsg(MSG_NO_TIMER);
-
- FreeArgs(RArgs);
- }
- else
- PrintFault(IoErr(), PROGNAME);
-
- FreeDosObject(DOS_RDARGS, MyRArgs);
- }
- else
- ErrorMsg(MSG_NO_RDARGS);
- }
-
- /* turn on the selected X10 units */
-
- void X10TurnOn(STRPTR * Targets)
- {
- OnOffDimHandler(Targets, 0, 2, MSG_TURN_ON);
- }
-
- /* turn off the selected X10 units */
-
- void X10TurnOff(STRPTR * Targets)
- {
- OnOffDimHandler(Targets, 0, 3, MSG_TURN_OFF);
- }
-
- /* set the selected targets to the specified dim level */
-
- void X10Dim(STRPTR * Targets, ULONG DimLevel)
- {
- if (DimLevel < 1 || DimLevel > 16) {
- ErrorMsg(MSG_INVALID_DIM_LEVEL, DimLevel);
- return;
- }
-
- DimLevel--;
-
- OnOffDimHandler(Targets, DimLevel, 5, MSG_DIM);
- }
-
- /* loop that handles X10TurnOn, X10TurnOff and X10Dim */
-
- void OnOffDimHandler(STRPTR * Targets, ULONG DimLevel, ULONG Function, LONG Msg)
- {
- int hc;
- int unit;
- UBYTE *currentTarget;
-
- if (!Targets)
- ErrorMsg(MSG_NO_UNITS_SPECIFIED);
- else
- do {
- currentTarget = *Targets;
-
- hc = X10GetHC(*currentTarget++);
-
- if (hc == -1)
- ErrorMsg(MSG_INVALID_UNIT, *Targets);
- else {
- unit = atol(currentTarget);
-
- if (unit < 1 || unit > 16)
- ErrorMsg(MSG_INVALID_UNIT, *Targets);
- else {
- unit--;
- if (!(X10SendDirectCmd(hc, unit, Function, DimLevel)))
- ErrorMsg(MSG_CP290_ERROR_DIRECT, GetString(&LocaleInfo, Msg), *Targets);
- }
- }
-
- Targets++;
-
- } while (*Targets);
- }
-
- /* set the base housecode for the buttons on the controller unit */
-
- void X10SetBaseHC(STRPTR BaseHC)
- {
- int hc;
- UBYTE Buf[18];
-
- if (!BaseHC)
- ErrorMsg(MSG_NO_BASE_HC);
- else {
- hc = X10GetHC(BaseHC[0]);
-
- if (hc == -1)
- ErrorMsg(MSG_INVALID_BASE_HC, BaseHC[0]);
- else {
- memset(Buf, 0xFF, 16);
- Buf[16] = 0;
- Buf[17] = HouseCode[hc];
-
- ClearSerial();
- SerWrite(Buf, 18);
- if (!X10WaitForAck(FALSE))
- ErrorMsg(MSG_CP290_ERROR_BASEHC);
- }
- }
- }
-
- /* set the controller unit's clock */
-
- void X10SetClock(void)
- {
- UBYTE Buf[21];
- struct timeval tr_time;
- ULONG secs;
- int DOW;
-
- GetSysTime(&tr_time);
- secs = tr_time.tv_secs % SECSINDAY;
-
- memset(Buf, 0xFF, 16);
- Buf[16] = 2;
-
- Buf[18] = secs / SECSINHOUR;
- secs %= SECSINHOUR;
- Buf[17] = secs / SECSINMINUTE;
-
- DOW = ((tr_time.tv_secs / SECSINDAY) % 7) - 1;
- if (DOW == -1)
- DOW = 6;
-
- Buf[19] = 1L << DOW;
-
- Buf[20] = Buf[17] + Buf[18] + Buf[19];
-
- ClearSerial();
- SerWrite(Buf, 21);
- if (!X10WaitForAck(FALSE))
- ErrorMsg(MSG_CP290_ERROR_SETCLOCK);
- }
-
- /* runs a diagnostic test on the x10 interface */
-
- void X10Diagnostic(void)
- {
- UBYTE Buf[17];
- int index;
- UWORD raw;
- UBYTE BaseHC;
- STRPTR DOW;
-
- /*
- * send the code for a self diagnostic and wait for the unit's
- * response
- */
-
- memset(Buf, 0xFF, 16);
- Buf[16] = 7;
-
- ClearSerial();
- SerWrite(Buf, 17);
-
- for (index = 0;; index++) {
- raw = SerGetRawChar(15);
-
- if (raw == TIMEOUT) {
- ErrorMsg(MSG_CP290_ERROR_DIAG, GetString(&LocaleInfo, MSG_TIMEOUT));
- return;
- }
-
- if (raw == 0xFF)
- index++;
- else if (index > 5)
- if ((raw & 1) == 1) {
- ErrorMsg(MSG_CP290_ERROR_DIAG, GetString(&LocaleInfo, MSG_STATUS_FLAG));
- return;
- }
- else
- break;
- }
-
- /*
- * if the interface passed the diagnositc test then query it about
- * the base housecode and what time it thinks it is and display this
- * to the user as part of the status message.
- */
-
- memset(Buf, 0xFF, 16);
- Buf[16] = 4;
-
- ClearSerial();
- SerWrite(Buf, 17);
-
- for (index = 0;;) {
- raw = SerGetRawChar(15);
-
- if (raw == TIMEOUT) {
- ErrorMsg(MSG_CP290_ERROR_NO_RESPONSE);
- return;
- }
-
- if (raw == 0xFF) {
- Buf[index++] = raw;
- break;
- }
- }
-
- while (index < 12) {
- raw = SerGetRawChar(2);
-
- if (raw == TIMEOUT) {
- ErrorMsg(MSG_CP290_ERROR_READING, GetString(&LocaleInfo, MSG_TIMEOUT));
- return;
- }
-
- Buf[index++] = raw;
- }
-
- if (Buf[11] != Buf[7] + Buf[8] + Buf[9] + Buf[10]) {
- ErrorMsg(MSG_CP290_ERROR_READING, GetString(&LocaleInfo, MSG_CHECKSUM));
- return;
- }
-
- for (index = 0; index < 16; index++)
- if (HouseCode[index] == Buf[10])
- BaseHC = 'A' + index;
-
- switch (Buf[9]) {
- case 64:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_1);
- else
- DOW = "Sunday";
- break;
-
- case 32:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_7);
- else
- DOW = "Saturday";
- break;
-
- case 16:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_6);
- else
- DOW = "Friday";
- break;
-
- case 8:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_5);
- else
- DOW = "Thursday";
- break;
-
- case 4:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_4);
- else
- DOW = "Wednesday";
- break;
-
- case 2:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_3);
- else
- DOW = "Tuesday";
- break;
-
- case 1:
- if (LocaleBase)
- DOW = GetLocaleStr(DefaultLocale, DAY_2);
- else
- DOW = "Monday";
- break;
-
- default:
- DOW = "???";
- break;
- };
-
- MyPrintf(MSG_CP290_PASSED_DIAG, BaseHC, DOW, Buf[8], Buf[7]);
-
- /*
- * when a diagnostic is run, the interface whacks out all of its
- * memory. Thus, if we tried to upload data from it we would get
- * garbage. we also have garbage sitting there that might cause
- * funny events to happen. So we set the unit's base housecode to
- * what we were just told it was by the interface. This causes the
- * interface to properly reset its memory so that we don't have bogus
- * data sitting in it.
- */
- sprintf(Buf, "%lc", BaseHC);
- X10SetBaseHC(Buf);
-
- return;
- }
-
- /*
- * look at the character passed in and decide if it's a valid house code or
- * not. translate it into the appripriate index value for use with the
- * controller unit if it's valid. else return -1.
- */
-
- int X10GetHC(UBYTE Char)
- {
- if (isalpha(Char)) {
- Char = tolower(Char);
-
- if (Char >= 'a' && Char <= 'p')
- return Char - 'a';
- }
-
- return -1;
- }
-
- /* build an x10 direct command to turn a specified unit on, off, etc. */
-
- BOOL X10SendDirectCmd(int HC, int Unit, ULONG Function, ULONG DimLevel)
- {
- UBYTE Buf[22];
- int unitByte;
-
- memset(Buf, 0xFF, 16);
- Buf[16] = 1;
- Buf[17] = ((DimLevel & 0x0F) << 4L) | (Function & 0x0F);
- Buf[18] = HouseCode[HC];
-
- if (Unit < 8) {
- Buf[19] = 0;
- unitByte = 20;
- }
- else {
- Buf[20] = 0;
- unitByte = 19;
- Unit -= 8;
- }
-
- Buf[unitByte] = 1L << (7 - Unit);
-
- Buf[21] = Buf[17] + Buf[18] + Buf[19] + Buf[20];
-
- ClearSerial();
- SerWrite(Buf, 22);
- return X10WaitForAck(TRUE);
- }
-
- /*
- * wait for the ack message from the controller unit. we return the ack's
- * status bit as either true or false
- */
-
- BOOL X10WaitForAck(BOOL WaitForUploadReport)
- {
- int SYNCs;
- UWORD raw;
-
- /* look for ack to our command */
- for (SYNCs = 0; SYNCs < 16; SYNCs++) {
- raw = SerGetRawChar(15);
-
- if (raw == TIMEOUT)
- return FALSE;
-
- if (raw != 0xFF)
- SYNCs = 255;
- }
-
- if (WaitForUploadReport) {
- /* look for upload report */
- for (SYNCs = 0; SYNCs < 16; SYNCs++) {
- raw = SerGetRawChar(15);
-
- if (raw == TIMEOUT)
- return FALSE;
-
- if (raw != 0xFF)
- SYNCs = 255;
- }
-
- /* suck the remaining characters in the upload report */
- do {
- raw = SerGetRawChar(1);
- } while (raw != TIMEOUT);
- }
-
- return TRUE;
- }
-